
/*
	This file included all classes and functions
*/

#include <string>
#include <iostream>

#pragma once

typedef unsigned int UINT;

namespace Terminal
{
	class Date
	{
	public:
		Date(UINT year, UINT month, UINT day, UINT hour, UINT minute, UINT second);


		// Change
		void changeTo(UINT year, UINT month, UINT day, UINT hour, UINT minute, UINT second);


		// Input parts
		void setYear(UINT year);
        void setMonth(UINT month);
        void setDay(UINT day);
        void setHour(UINT hour);
        void setMinute(UINT minute);
        void setSecond(UINT second);


		// Output parts
		UINT year();
		UINT month();
		UINT day();
		UINT hour();
		UINT minute();
		UINT second();
        const char * toString();

		// Operators
		bool  operator==(Date& date); // Return if this equals to parameter date
		UINT  operator- (Date& date); // Return interval between two Date (day)
		void  operator= (Date& date); // Copy parameter date's data to this class
        bool  operator> (Date& date);
        bool  operator< (Date& date);
        
        friend std:: ostream &operator << (std::ostream &os, Date &date);

	private:
		// Attributes
		UINT m_iYear, m_iMonth, m_iDay;
		UINT m_iHour, m_iMinute, m_iSecond;
	};

	class Task
	{
	public:
		Task(std::string name, std::string label, std::string remarks,
			Date* pBegDate, Date* pEndDate, int imp = 0);
		~Task();


		// Input parts
		void add(Task* newTask);
		void add(std::string name, std::string label, std::string remarks,
			Date* pBegDate, Date* pEndDate, int imp = 0);
		Task* remove(std::string name);

		void setName(std::string name);
		void setLabels(std::string labels);
		void setRemarks(std::string remarks);
		void setBegDate(Date* date);
		void setEndDate(Date* date);
		void setImportance(int imp);


		// Output parts
		Task* at(int index);
		Task* get(std::string name);

		Task* next();
		Task* pre();

		const char * name();
		const char * label();
		const char * remarks();
		Date*       begDate();
		Date*       endDate();
		int         Importance();
        const char * toString();

        
        //New methods
        void swapWith(Task *t);
        friend std:: ostream &operator << (std::ostream &os, Task &task);

	protected:
		void  setPre(Task* t);
		Task* getPre();
		void  setNext(Task* t);
		Task* getNext();

	private:
		// Attributes
		std::string m_strName;
		std::string m_strLabel;
		std::string m_strRemarks;
		Date*       m_pBegDate;
		Date*       m_pEndDate;
		int         m_iImportance;

		// Chain table
		Task* m_pPreTask;
		Task* m_pNextTask;
	};

	class Plan
	{
	public:
		Plan(std::string name, std::string label, std::string remarks);
		~Plan();


		// Input parts
		void add(Plan* newPlan);
		void add(std::string name, std::string label, std::string remarks);
		Plan* remove(std::string name);

		void setName(std::string name);
		void setLabel(std::string label);
		void setRemarks(std::string remark);


		// Output parts
		Plan* at(int index);
		Plan* get(std::string name);

		Plan* next();
		Plan* pre();

		const char* name();
		const char* label();
		const char* remarks();
 
		Task* getFirstTask();
        
        const char * toString();
        
        
        //New methods
        void  addTask(Task *t);
        void  removeTask(std::string name);
        Task* findTask(std::string name);
        Date* getBegDate();
        Date* getEndDate();
        
        void swapWith(Plan *p);
        friend std:: ostream &operator << (std::ostream &os, Plan &plan);


	protected:
		// These function only can be used in chain table operatons
		Plan*  getPre();
		void   setPre(Plan *p);
		Plan*  getNext();
		void   setNext(Plan *p);

	private:
		// Attributes
		std::string m_strName;
		std::string m_strLabel;
		std::string m_strRemarks;

		// Chain table
		Plan* m_pPrePlan;
		Plan* m_pNextPlan;
		Task* m_pFirstTask;
	};
    
    
    //Functiooooon
    //sort
    void STimeSort(Task *h);
    void ETimeSort(Task *h);
    void ImpSort(Task *h);
    
    void STimeSort(Plan *h);
    void ETimeSort(Plan *h);
    void ImpSort(Plan *h);
    
    //size
    int GetLength(Plan *p);
    int GetLength(Task *p);
    
    //I&O
    Plan *TOpen(std::string fileName);
    void TSave(std::string fileName, Plan *pp);
    
    //check today task
    Task* checkToday(Plan *p, Date *today);
    
}
